import { resolve, dirname } from "node:path";
import { readdirSync, existsSync } from "node:fs";
import fg from "fast-glob";

// --- 辅助函数：查找并缓存 Monorepo 根目录 ---
let monorepoRootCache;

/**
 * 严谨地查找 monorepo 根目录（包含 pnpm-workspace.yaml 的目录）。
 * @param {string} startDir - 开始查找的目录，默认为当前工作目录。
 * @returns {string} - monorepo 根目录的绝对路径。
 * @throws {Error} - 如果找不到 pnpm-workspace.yaml 文件。
 */
function findMonorepoRoot(startDir = process.cwd()) {
  if (monorepoRootCache) {
    return monorepoRootCache;
  }

  let currentDir = startDir;
  // 循环向上查找，直到文件系统的根目录
  while (currentDir !== dirname(currentDir)) {
    const markerPath = resolve(currentDir, "pnpm-workspace.yaml");
    if (existsSync(markerPath)) {
      monorepoRootCache = currentDir;
      return currentDir;
    }
    currentDir = dirname(currentDir);
  }

  throw new Error("Could not find 'pnpm-workspace.yaml'. This plugin must be used within a pnpm monorepo environment.");
}

// --- 虚拟模块定义 ---
const VIRTUAL_MODULE_ID = "virtual:app-routes-collection";
const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;

/**
 * 将字符串转换为有效的 JavaScript 变量名。
 * @param {string} name - e.g., "rent-qyz-boss"
 * @returns {string} - e.g., "rent_qyz_boss"
 */
function toValidIdentifier(name) {
  return name.replace(/[^a-zA-Z0-9_$]/g, "_");
}

/**
 * 一个 Vite 插件，用于扫描 `apps` 目录下所有项目的视图文件，
 * 并通过一个虚拟模块，将每个项目的路由列表作为独立的命名导出提供。
 */
function GenerateAppRoutesCollection() {
  const monorepoRoot = findMonorepoRoot();
  const appsRoot = resolve(monorepoRoot, "apps");

  return {
    name: "vite-plugin-generate-app-routes-collection",

    resolveId(id) {
      if (id === VIRTUAL_MODULE_ID) {
        return RESOLVED_VIRTUAL_MODULE_ID;
      }
    },

    async load(id) {
      if (id !== RESOLVED_VIRTUAL_MODULE_ID) {
        return;
      }

      if (!existsSync(appsRoot)) {
        console.error(`[${this.name}] Error: 'apps' directory not found at path: ${appsRoot}`);
        return "export {}; // Plugin Error: 'apps' directory not found.";
      }

      const appDirs = readdirSync(appsRoot, { withFileTypes: true })
        .filter(dirent => dirent.isDirectory())
        .map(dirent => dirent.name);

      const patterns = appDirs.map(appDir => resolve(appsRoot, appDir, "src/views/**/*.vue").replace(/\\/g, "/"));
      const files = await fg(patterns, { onlyFiles: true, absolute: true });

      const routesByApp = {};

      for (const file of files) {
        const match = file.match(/apps\/(?<appName>[^/]+)\/src\/views\/(?<componentPath>.+)\.vue$/);
        if (!match?.groups) continue;

        const { appName, componentPath } = match.groups;

        // 沿用你之前的过滤逻辑
        if (
          /error\//.test(componentPath) ||
          componentPath.startsWith("login") ||
          componentPath.includes("components")
        ) {
          continue;
        }

        if (!routesByApp[appName]) {
          routesByApp[appName] = [];
        }

        routesByApp[appName].push({ label: componentPath, value: componentPath });
      }

      // 生成一个包含所有数据的对象，并准备导出列表
      let fileContent =
        "// This file is generated by vite-plugin-generate-app-routes-collection. Do not edit manually.\n";
      const exportNames = [];

      for (const appName in routesByApp) {
        const identifier = toValidIdentifier(appName);
        const data = JSON.stringify(routesByApp[appName], null, 2);
        // 为每个应用定义一个常量
        fileContent += `const ${identifier} = ${data};\n`;
        // 将常量名添加到导出列表中
        exportNames.push(identifier);
      }

      // 添加一个集中的具名导出语句
      if (exportNames.length > 0) {
        fileContent += `\nexport { ${exportNames.join(", ")} };\n`;
      }

      return fileContent;
    },
  };
}

export default GenerateAppRoutesCollection;
